package AI;

import Bots.Bots;
import Bots.Buffer;
import cz.cuni.amis.pogamut.base.communication.worldview.event.IWorldEventListener;
import cz.cuni.amis.pogamut.base.communication.worldview.listener.annotation.EventListener;
import cz.cuni.amis.pogamut.base.communication.worldview.listener.annotation.ObjectClassEventListener;
import cz.cuni.amis.pogamut.base.utils.guice.AgentScoped;
import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
import cz.cuni.amis.pogamut.base3d.worldview.object.event.WorldObjectAppearedEvent;
import cz.cuni.amis.pogamut.ut2004.agent.module.utils.TabooSet;
import cz.cuni.amis.pogamut.ut2004.agent.navigation.NavigationState;
import cz.cuni.amis.pogamut.ut2004.agent.navigation.UT2004Navigation;
import cz.cuni.amis.pogamut.ut2004.agent.navigation.UT2004PathAutoFixer;
import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004BotModuleController;
import cz.cuni.amis.pogamut.ut2004.communication.messages.ItemType;
import cz.cuni.amis.pogamut.ut2004.communication.messages.UT2004ItemType;
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbcommands.*;
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.*;
import cz.cuni.amis.pogamut.ut2004.utils.UT2004BotRunner;
import cz.cuni.amis.pogamut.ut2004.utils.UnrealUtils;
import cz.cuni.amis.utils.collections.MyCollections;
import cz.cuni.amis.utils.exception.PogamutException;
import cz.cuni.amis.utils.flag.FlagListener;

import javax.vecmath.Vector3d;
import java.util.ArrayList;
import java.util.List;

@AgentScoped
public class TRAINING extends UT2004BotModuleController<UT2004Bot> {
    //主程序1
    public static int agent_num = 2;
    public static int skill = 1;

    public static Bots[] expertbots;

    public static Bots[] falconbots;
    public static FALCON[] falconagent;

    public static Bots[] shootbots;
    public static FALCON[] shootagent;

    public static Bots[] focusbots;
    public static FALCON[] focusagent;

    public static Bots[] movebots;
    public static FALCON[] moveagent;

    public static boolean rw1 = false;
    public static boolean rw2 = false;

    //public static TDFALCON_BOT falconAI;
    public static void main(String[] args) throws PogamutException, Exception {
        expertbots = new Bots[agent_num];

        falconbots = new Bots[agent_num];
        falconagent = new FALCON[agent_num];


        shootbots = new Bots[agent_num];
        shootagent = new FALCON[agent_num];

        focusbots = new Bots[agent_num];
        focusagent = new FALCON[agent_num];

        movebots = new Bots[agent_num];
        moveagent = new FALCON[agent_num];

        for (int i = 0; i < agent_num; i++) {

            shootagent[i] = new FALCON(i, Shooting_numState, Shooting_numAction, rw1, "shootagent");
            shootbots[i] = new Bots(i, Shooting_numState, Shooting_numAction, rw2, "shootbots");

            focusagent[i] = new FALCON(i, Focus_numState, Focus_numAction, rw1, "focusagent");
            focusbots[i] = new Bots(i, Focus_numState, Focus_numAction, rw2, "focusbots");

            falconagent[i] = new FALCON(i, FALCON_numState, FALCON_numState, rw1, "falconagent");
            falconbots[i] = new Bots(i, FALCON_numState, FALCON_numState, rw2, "falconbots");

            moveagent[i] = new FALCON(i, Move_numState, Move_numState, rw1, "moveagent");
            movebots[i] = new Bots(i, Move_numState, Move_numState, rw2, "movebots");

            expertbots[i] = new Bots(i, expert_numState, expert_numAction, rw2, "expertbots");

        }

        new UT2004BotRunner(TRAINING.class, "Hunter").setMain(true).startAgents(agent_num);
    }

    Self self = null;
    //主线程准备2
    public TabooSet<Item> tabooItems;
    private UT2004PathAutoFixer autoFixer;

    @Override
    public void prepareBot(UT2004Bot bot) {
        autoFixer = new UT2004PathAutoFixer(bot, navigation.getPathExecutor(), fwMap, aStar, navBuilder);
        tabooItems = new TabooSet<Item>(bot);

        getWorldView().addEventListener(BotDamaged.class, botDamagedListener);
        getWorldView().addEventListener(BotKilled.class, BotKilledListener);
        getWorldView().addEventListener(PlayerDamaged.class, PlayerDamagedListener);
        getWorldView().addEventListener(PlayerKilled.class, PlayerKilledListener);
        getWorldView().addEventListener(ItemPickedUp.class, ItemPickedUpListener);
        getWorldView().addEventListener(HearNoise.class, HearNoiseListener);

        // listeners
        navigation.getState().addListener(new FlagListener<NavigationState>() {

            @Override
            public void flagChanged(NavigationState changedValue) {
                switch (changedValue) {
                    case PATH_COMPUTATION_FAILED:
                    case STUCK:
                        navigation.stopNavigation();
                        break;

                    case TARGET_REACHED:
                        navigation.stopNavigation();
                        break;
                }
            }
        });


        weaponPrefs.addGeneralPref(UT2004ItemType.LIGHTNING_GUN, true);
        weaponPrefs.addGeneralPref(UT2004ItemType.SHOCK_RIFLE, true);
        weaponPrefs.addGeneralPref(UT2004ItemType.MINIGUN, false);
        weaponPrefs.addGeneralPref(UT2004ItemType.FLAK_CANNON, true);
        weaponPrefs.addGeneralPref(UT2004ItemType.ROCKET_LAUNCHER, true);
        weaponPrefs.addGeneralPref(UT2004ItemType.LINK_GUN, true);
        weaponPrefs.addGeneralPref(UT2004ItemType.ASSAULT_RIFLE, true);
        weaponPrefs.addGeneralPref(UT2004ItemType.BIO_RIFLE, true);
    }

    //初始化3
    //重置
    protected void reset(Bots bots) {
        bot.getBotName().setInfo("RESET");
        bots.reset();
        for (int i = 0; i < bots.numState; i++) {
            bots.CurrentStat[i] = bots.stat[i];
        }
        navigation.stopNavigation();
        return;
    }

    public int agt;

    //private static int  instanceCount =0;
    @Override
    public Initialize getInitializeCommand() {
        agt = (int) Thread.currentThread().getName().toCharArray()[6] - 49;
        if (agt == 0) {
            reset(falconbots[agt]);
            reset(shootbots[agt]);
            reset(focusbots[agt]);
            reset(movebots[agt]);
            return new Initialize().setName("TDFALCON").setDesiredSkill(5);
        } else if (agt == 1) {
            reset(expertbots[agt]);
            reset(falconbots[agt]);
            reset(shootbots[agt]);
            reset(focusbots[agt]);
            reset(movebots[agt]);
            return new Initialize().setName("EXPERT").setDesiredSkill(3);
        }
        return new Initialize().setName("Error").setDesiredSkill(skill);
    }

    protected UT2004Navigation navigationAStar;

    //4

    public static final String FRONT = "frontRay";
    public static final String LEFT45 = "left45Ray";
    public static final String LEFT90 = "left90Ray";
    public static final String RIGHT45 = "right45Ray";
    public static final String RIGHT90 = "right90Ray";


    @Override
    public void botInitialized(GameInfo info, ConfigChange currentConfig, InitedMessage init) {
        final int rayLength = (int) (UnrealUtils.CHARACTER_COLLISION_RADIUS * 2);
        boolean fastTrace = true;
        boolean floorCorrection = false;
        boolean traceActor = false;
        getAct().act(new RemoveRay("All"));
        raycasting.createRay(LEFT45, new Vector3d(1, -1, 0), rayLength, fastTrace, floorCorrection, traceActor);
        raycasting.createRay(FRONT, new Vector3d(1, 0, 0), rayLength, fastTrace, floorCorrection, traceActor);
        raycasting.createRay(RIGHT45, new Vector3d(1, 1, 0), rayLength, fastTrace, floorCorrection, traceActor);
        raycasting.createRay(LEFT90, new Vector3d(0, -1, 0), rayLength, fastTrace, floorCorrection, traceActor);
        raycasting.createRay(RIGHT90, new Vector3d(0, 1, 0), rayLength, fastTrace, floorCorrection, traceActor);

        raycasting.getAllRaysInitialized().addListener(new FlagListener<Boolean>() {
            public void flagChanged(Boolean changedValue) {
                movebots[agt].left90 = raycasting.getRay(LEFT90);
                movebots[agt].left45 = raycasting.getRay(LEFT45);
                movebots[agt].front = raycasting.getRay(FRONT);
                movebots[agt].right90 = raycasting.getRay(RIGHT90);
                movebots[agt].right45 = raycasting.getRay(RIGHT45);
            }
        });

        raycasting.endRayInitSequence();
        getAct().act(new Configuration().setDrawTraceLines(true).setAutoTrace(true));

    }


    //产生5
    @Override
    public void botFirstSpawn(GameInfo gameInfo, ConfigChange config, InitedMessage init, Self self) {
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //逻辑
    @Override
    public void logic() {
        if (agt == 0) {
            //FALCON_perf(falconagent[agt],bots[agt]);
            Shooting_perf(shootagent[agt], shootbots[agt]);
            Focus_perf(focusagent[agt], focusbots[agt]);
            //Move_perf(moveagent[agt],movebots[agt]);
        }
        if (agt == 1) {
            //FALCON_perf(falconagent[agt],falconbots[agt]);
            EXPERT_perf(expertbots[agt]);
            //Shooting_perf(shootagent[agt],shootbots[agt]);
            //Focus_perf(focusagent[agt],focusbots[agt]);
            //shootagent[agt].use_buff=1;
            //focusagent[agt].use_buff=1;
            //shootagent[agt].access=0;
            //focusagent[agt].access=0;
        }


    }


    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    //被打
    public IWorldEventListener<BotDamaged> botDamagedListener = new IWorldEventListener<BotDamaged>() {
        @Override
        public void notify(BotDamaged event) {
            expertbots[agt].getdamage += (double) event.getDamage();
            falconbots[agt].getdamage += (double) event.getDamage();
            focusbots[agt].getdamage += (double) event.getDamage();
            shootbots[agt].getdamage += (double) event.getDamage();
            movebots[agt].getdamage += (double) event.getDamage();
        }
    };


    //打人
    public IWorldEventListener<PlayerDamaged> PlayerDamagedListener = new IWorldEventListener<PlayerDamaged>() {
        @Override
        public void notify(PlayerDamaged event) {
            expertbots[agt].hitdamage += (double) event.getDamage();
            falconbots[agt].hitdamage += (double) event.getDamage();
            shootbots[agt].hitdamage += (double) event.getDamage();
            focusbots[agt].hitdamage += (double) event.getDamage();
            movebots[agt].hitdamage += (double) event.getDamage();
        }
    };

    //被杀
    public IWorldEventListener<BotKilled> BotKilledListener = new IWorldEventListener<BotKilled>() {
        @Override
        public void notify(BotKilled event) {
            expertbots[agt].r -= 1;
            expertbots[agt].end = true;
            expertbots[agt].die++;
            expertbots[agt].reset();

            falconbots[agt].r -= 1;
            falconbots[agt].end = true;
            falconbots[agt].die++;
            falconbots[agt].reset();

            focusbots[agt].r -= 1;
            focusbots[agt].end = true;
            focusbots[agt].die++;
            focusbots[agt].reset();

            shootbots[agt].r -= 1;
            shootbots[agt].end = true;
            shootbots[agt].die++;
            shootbots[agt].reset();

            movebots[agt].r -= 1;
            movebots[agt].end = true;
            movebots[agt].die++;
            movebots[agt].reset();


            if (rw1) {
                try {
                    falconagent[agt].writefile(agt, "falconagent");
                    shootagent[agt].writefile(agt, "shootagent");
                    focusagent[agt].writefile(agt, "focusagent");
                    moveagent[agt].writefile(agt, "moveagent");
                } catch (Exception e) {
                    ;
                }
            }
            if (rw2) {
                try {
                    falconbots[agt].writefile(agt, "falconbots");
                    shootbots[agt].writefile(agt, "shootbots");
                    focusbots[agt].writefile(agt, "focusbots");
                    movebots[agt].writefile(agt, "movebots");
                } catch (Exception e) {
                    ;
                }
            }
            navigation.stopNavigation();
        }
    };

    //杀敌
    public IWorldEventListener<PlayerKilled> PlayerKilledListener = new IWorldEventListener<PlayerKilled>() {
        @Override
        public void notify(PlayerKilled event) {
            expertbots[agt].r += 1.0;
            expertbots[agt].kill++;
            expertbots[agt].end = true;
            expertbots[agt].enemy = null;

            falconbots[agt].r += 1.0;
            falconbots[agt].kill++;
            falconbots[agt].end = true;
            falconbots[agt].enemy = null;

            shootbots[agt].r += 1.0;
            shootbots[agt].kill++;
            shootbots[agt].end = true;
            shootbots[agt].enemy = null;

            shootbots[agt].r += 1.0;
            shootbots[agt].kill++;
            focusbots[agt].kill++;
            focusbots[agt].enemy = null;

            movebots[agt].r += 1.0;
            movebots[agt].kill++;
            movebots[agt].end = true;
            movebots[agt].enemy = null;
            navigation.stopNavigation();
        }
    };
    public IWorldEventListener<ItemPickedUp> ItemPickedUpListener = new IWorldEventListener<ItemPickedUp>() {
        @Override
        public void notify(ItemPickedUp event) {
            focusbots[agt].r += 0.25;
            falconbots[agt].r += 0.25;
        }
    };

    public IWorldEventListener<HearNoise> HearNoiseListener = new IWorldEventListener<HearNoise>() {
        @Override
        public void notify(HearNoise event) {
            if (focusbots[agt].enemy == null)
                focusbots[agt].enemy = players.getPlayer(event.getSource());
        }
    };


    //碰面
    @ObjectClassEventListener(eventClass = WorldObjectAppearedEvent.class, objectClass = Player.class)
    public void playerAppeared(WorldObjectAppearedEvent<Player> event) {
        ;
    }

    @EventListener(eventClass = TeamChat.class)
    public void teamChat(TeamChat event) {
        ;
    }


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


    static int expert_numState = (12) * 2;

    //状态采样
    public void EXPERT_observe(Bots bots) {
        int i = 0;
        Player enemy;
        bots.observe();
        //血量
        bots.stat[2 * i] = (double) info.getHealth() / 100.0;
        if (bots.stat[2 * i] > 1) bots.stat[2 * i] = 1.0;
        bots.stat[2 * i + 1] = 1 - bots.stat[2 * i];
        i += 1;
        enemy = players.getNearestVisiblePlayer(players.getVisibleEnemies().values());
        if (enemy != null) {
            bots.stat[2 * i] = (double) (info.getLocation().getDistance(enemy.getLocation()) / 1000.0);
            if (bots.stat[2 * i] > 1) bots.stat[2 * i] = 1.0;
            bots.stat[2 * i + 1] = 1 - bots.stat[2 * i];
        }

        i += 1;
        //有敌人
        if (enemy != null) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //射击
        if (bots.shooting) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否被攻击
        if (senses.isBeingDamaged()) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有激光
        if (weaponry.hasWeapon(UT2004ItemType.LIGHTNING_GUN)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有minigun
        if (weaponry.hasWeapon(UT2004ItemType.MINIGUN)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有闪光炮
        if (weaponry.hasWeapon(UT2004ItemType.FLAK_CANNON)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有火箭筒
        if (weaponry.hasWeapon(UT2004ItemType.ROCKET_LAUNCHER)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有连接枪
        if (weaponry.hasWeapon(UT2004ItemType.LINK_GUN)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有突击步枪
        if (weaponry.hasWeapon(UT2004ItemType.ASSAULT_RIFLE)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有生物枪
        if (weaponry.hasWeapon(UT2004ItemType.BIO_RIFLE)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;
    }


    static int expert_numAction = 5;

    public void stopshooting() {
        if (!players.canSeeEnemies() && (info.isShooting() || info.isSecondaryShooting())) {
            getAct().act(new StopShooting());
        }
    }

    public void EXPERT_Engage(Bots bots) {
        bot.getBotName().setInfo("stateEngage");

        double distance = Double.MAX_VALUE;
        if (bots.enemy == null || !bots.enemy.isVisible()) {
            bots.enemy = players.getNearestVisiblePlayer(players.getVisibleEnemies().values());
            if (bots.enemy == null) {
                return;
            }
        }

        if (!bots.enemy.isVisible()) {
            if (info.isShooting() || info.isSecondaryShooting()) {
                getAct().act(new StopShooting());
            }
            bots.runningToPlayer = false;
        } else {
            distance = info.getLocation().getDistance(bots.enemy.getLocation());
            if (shoot.shoot(weaponPrefs, bots.enemy) != null) {
                bots.shooting = true;
            }
        }
        int decentDistance = Math.round(random.nextFloat() * 800) + 200;
        if (!bots.enemy.isVisible() || !bots.shooting || decentDistance < distance) {
            if (!bots.runningToPlayer) {
                navigation.navigate(bots.enemy);
                bots.runningToPlayer = true;
            }
        } else {
            bots.runningToPlayer = false;
            navigation.stopNavigation();
        }

        bots.item = null;
    }

    public void EXPERT_Rotate(Bots bots) {
        bot.getBotName().setInfo("Rotate");
        if (navigation.isNavigating()) {
            navigation.stopNavigation();
            bots.item = null;
        }
        getAct().act(new Rotate().setAmount(32000));
    }

    public void EXPERT_Pursue(Bots bots) {
        if (bots.enemy != null) {
            navigation.navigate(bots.enemy);
            bots.item = null;
        } else {
        }
    }

    public int pursueCount = 0;

    public void EXPERT_MedKit(Bots bots) {
        bot.getBotName().setInfo("MEDKIT");
        Item item = items.getPathNearestSpawnedItem(ItemType.Category.HEALTH);
        if (item == null) {
            EXPERT_RunAroundItems(bots);
        } else {
            navigation.navigate(item);
            bots.item = item;
        }
    }

    public void EXPERT_RunAroundItems(Bots bots) {
        bot.getBotName().setInfo("stateRunAroundItems");
        if (navigation.isNavigatingToItem()) return;
        bots.interesting = new ArrayList<Item>();
        for (ItemType itemType : ItemType.Category.WEAPON.getTypes()) {
            if (!weaponry.hasLoadedWeapon(itemType)) bots.interesting.addAll(items.getSpawnedItems(itemType).values());
        }
        for (ItemType itemType : ItemType.Category.ARMOR.getTypes()) {
            bots.interesting.addAll(items.getSpawnedItems(itemType).values());
        }
        bots.interesting.addAll(items.getSpawnedItems(UT2004ItemType.U_DAMAGE_PACK).values());
        if (info.getHealth() < 100) {
            bots.interesting.addAll(items.getSpawnedItems(UT2004ItemType.HEALTH_PACK).values());
        }

        Item item = MyCollections.getRandom(tabooItems.filter(bots.interesting));
        if (item == null) {
            if (navigation.isNavigating()) return;
            navigation.navigate(navPoints.getRandomNavPoint());
        } else {
            bots.item = item;
            navigation.navigate(item);
        }
    }


    public int healthLevel = 75;

    //ai部分
    public void EXPERT_perf(Bots bots) {
        if (players.canSeeEnemies() && weaponry.hasLoadedWeapon()) {
            EXPERT_Engage(bots);
            return;
        }
        if (info.isShooting() || info.isSecondaryShooting()) {
            getAct().act(new StopShooting());
        }
        if (senses.isBeingDamaged()) {
            this.EXPERT_Rotate(bots);
            return;
        }
        if (bots.enemy != null && weaponry.hasLoadedWeapon()) {
            this.EXPERT_Pursue(bots);
            return;
        }
        if (info.getHealth() < healthLevel) {
            this.EXPERT_MedKit(bots);
            return;
        }
        EXPERT_RunAroundItems(bots);
    }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    public void FALCON_reward_function(Bots bots) {
        double y = (double) info.getHealth() / 100.0 - bots.lastheal;

        if (!bots.end) {
            if (y > 0) {
                bots.r += 0.25;
            } else if (y < 0) {
                bots.r -= 0.25;
            }
            bots.lastheal = (double) info.getHealth() / 100.0;

            if (bots.hitdamage > 0) {
                bots.r += 0.75;
            }
            bots.hitdamage = 0;

            if (bots.r > 1) bots.r = 1;
        }
    }

    static int FALCON_numState = (2 + 3 + 7) * 2;

    //状态采样
    public void FALCON_observe(Bots bots) {

        int i = 0;
        bots.observe();

        //血量
        bots.stat[2 * i] = (double) info.getHealth() / 100.0;
        if (bots.stat[2 * i] > 1) bots.stat[2 * i] = 1.0;
        bots.stat[2 * i + 1] = 1 - bots.stat[2 * i];
        i += 1;


        Player enemy = players.getNearestVisiblePlayer(players.getVisibleEnemies().values());
        if (enemy != null) {
            bots.stat[2 * i] = (double) (info.getLocation().getDistance(enemy.getLocation()) / 1000.0);
            if (bots.stat[2 * i] > 1) bots.stat[2 * i] = 1.0;
            bots.stat[2 * i + 1] = 1 - bots.stat[2 * i];
        }

        i += 1;


        //有敌人
        if (enemy != null) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;


        //射击
        if (bots.shooting) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否被攻击
        if (senses.isBeingDamaged()) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有激光
        if (weaponry.hasWeapon(UT2004ItemType.LIGHTNING_GUN)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有minigun
        if (weaponry.hasWeapon(UT2004ItemType.MINIGUN)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有闪光炮
        if (weaponry.hasWeapon(UT2004ItemType.FLAK_CANNON)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有火箭筒
        if (weaponry.hasWeapon(UT2004ItemType.ROCKET_LAUNCHER)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有连接枪
        if (weaponry.hasWeapon(UT2004ItemType.LINK_GUN)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有突击步枪
        if (weaponry.hasWeapon(UT2004ItemType.ASSAULT_RIFLE)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有生物枪
        if (weaponry.hasWeapon(UT2004ItemType.BIO_RIFLE)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;


    }


    static int FALCON_numAction = 5;

    //拾取物品
    protected void FALCON_RunAroundItems(Bots bots) {
        bot.getBotName().setInfo("stateRunAroundItems");

        if (navigation.isNavigatingToItem()) {
            return;
        } else {
            bots.interesting = new ArrayList<Item>();
            for (ItemType itemType : ItemType.Category.WEAPON.getTypes()) {
                if (!weaponry.hasLoadedWeapon(itemType))
                    bots.interesting.addAll(items.getSpawnedItems(itemType).values());
            }
            bots.item = MyCollections.getRandom(tabooItems.filter(bots.interesting));
            if (bots.item != null) {
                navigation.navigate(bots.item);
            }
        }
    }

    //旋转
    protected void FALCON_Rotate(Bots bots) {
        bot.getBotName().setInfo("Rotate");

        navigation.stopNavigation();
        getAct().act(new Rotate().setAmount(32000));
        return;
    }

    //射击
    protected void FALCON_Engage(Bots bots) {
        bot.getBotName().setInfo("stateEngage");

        bots.enemy = players.getNearestVisiblePlayer(players.getVisibleEnemies().values());
        navigation.stopNavigation();
        if (bots.enemy != null) {
            if (shoot.shoot(weaponPrefs, bots.enemy) != null) {
                bots.shooting = true;
            }
        }
    }

    //医疗
    protected void FALCON_MedKit(Bots bots) {
        bot.getBotName().setInfo("MedKit");
        bots.item = items.getPathNearestSpawnedItem(ItemType.Category.HEALTH);
        if (bots.item != null) {
            navigation.navigate(bots.item);
        }
    }

    protected void FALCON_Pursue(Bots bots) {
        bot.getBotName().setInfo("PURSUE");
        if (bots.enemy != null) {
            navigation.navigate(bots.enemy);
        }
        bots.runningToPlayer = true;
    }


    public void FALCON_SelectVAct(Bots bots) {
        List<Item> interesting = new ArrayList<Item>();
        Player enemy;

        int i = 0;
        ///////////////////////////////////////
        bots.vact[i] = true;

        interesting = new ArrayList<Item>();
        for (ItemType itemType : ItemType.Category.WEAPON.getTypes()) {
            if (!weaponry.hasLoadedWeapon(itemType))
                interesting.addAll(items.getSpawnedItems(itemType).values());
        }
        for (ItemType itemType : ItemType.Category.ARMOR.getTypes()) {
            interesting.addAll(items.getSpawnedItems(itemType).values());
        }
        interesting.addAll(items.getSpawnedItems(UT2004ItemType.U_DAMAGE_PACK).values());
        Item item = MyCollections.getRandom(tabooItems.filter(interesting));
        if (item == null) {
            bots.vact[i] = false;
        }
        i += 1;
        ////////////////////////
        bots.vact[i] = true;

        if (bots.action == i) {
            bots.vact[i] = false;
        }
        i += 1;
        ////////////////////////////
        bots.vact[i] = true;

        enemy = players.getNearestVisiblePlayer(players.getVisibleEnemies().values());
        if (enemy == null) {
            bots.vact[i] = false;
        }

        if (enemy != null) {
            if (!enemy.isVisible()) {
                getAct().act(new StopShooting());
                bots.shooting = false;
            }
        } else {
            getAct().act(new StopShooting());
            bots.shooting = false;
        }

        i += 1;


        ///////////////////////////////////////
        bots.vact[i] = true;

        item = items.getPathNearestSpawnedItem(ItemType.Category.HEALTH);
        if (item == null) {
            bots.vact[i] = false;
        }


        i += 1;
        ///////////////////////////////////////////
        bots.vact[i] = true;
        if (bots.enemy == null) {
            bots.vact[i] = false;
        } else {
            bots.distance = info.getLocation().getDistance(bots.enemy.getLocation());
            if (bots.enemy.isVisible()) {
                bots.vact[i] = false;
            } else {
                bots.decentDistance = Math.round(random.nextFloat() * 1000) + 1000;
                if (bots.distance > bots.decentDistance) {
                    bots.vact[i] = false;
                    bots.enemy = null;
                }
            }
        }

        i += 1;
    }

    //选择动作
    public void FALCON_DoAct(Bots bots, int action) {
        int i = 0;
        if (action == i) {
            FALCON_RunAroundItems(bots);
            return;
        }
        i += 1;
        if (action == i) {
            FALCON_Rotate(bots);
            return;
        }
        i += 1;
        if (action == i) {
            FALCON_Engage(bots);
            return;
        }
        i += 1;
        if (action == i) {
            FALCON_MedKit(bots);
            return;
        }
        i += 1;
        if (action == i) {
            FALCON_Pursue(bots);
            return;
        }
        i += 1;
    }

    public double alpha = 1.0;

    public double P(int j, Bots bots) {
        double sum = 0;
        double p = Math.pow(bots.buff.get(j).p, alpha);
        for (int i = 0; i < bots.buff.size(); i++) {
            sum += Math.pow(bots.buff.get(i).p, alpha);
        }
        return p / sum;
    }

    public double maxw(Bots bots) {
        double m = -1;
        for (int i = 0; i < bots.buff.size(); i++) {
            if (m < bots.buff.get(i).w) {
                m = bots.buff.get(i).w;
            }
        }
        return m;
    }


    //ai部分
    double beta = 1.0;
    int K = 16;


    private void FALCON_LEARNING(FALCON agent, Bots bots) {
        double p[] = {(double) 0.5, (double) 0.5, (double) 0.5};
        if (agent.QEpsilon > 0.05) agent.QEpsilon -= agent.QEpsilonDecay;
        if (agent.use_buff == 1) {
            for (int k = 0; k < K; k++) {
                double rand = Math.random();
                int j = 0;
                for (int i = 0; i < bots.buff.size(); i++) {
                    rand -= P(i, bots);
                    if (rand > 0) {
                        j++;
                    } else {
                        break;
                    }
                }
                bots.buff.get(j).w = Math.pow(bots.buff.size() * P(j, bots), -beta) / maxw(bots);
                agent.Q_Function_update(bots.buff.get(j), p);
            }
            bots.buff.get(bots.buff.size() - 1).w = Math.pow(bots.buff.size() * P(bots.buff.size() - 1, bots), -beta) / maxw(bots);
            agent.Q_Function_update(bots.buff.get(bots.buff.size() - 1), p);

        } else if (agent.use_buff == 0) {
            agent.Q_Function_update(bots.buff.get(bots.buff.size() - 1), p);
        }

    }

    public int step = 0;
    static int WriteInTarget = 500;
    int KK = 128;
    double rewards = 0.0;


    private void FALCON_EVAL(FALCON agent, Bots bots) {
        if (agt == 0) {
            step++;
            if (step % WriteInTarget == 0) {

                //TD-error
                if (agent.view == 0) {
                    double y_except = 0.0;
                    for (int i = 0; i < KK; i++) {
                        int j = (int) (Math.random() * bots.buff.size());
                        y_except += agent.eval(bots.buff.get(j));
                    }
                    System.out.println("TD1");
                    System.out.println("y_except");
                    System.out.println(y_except / KK);
                } else if (agent.view == 1) {
                    //rewards
                    System.out.println("rewards");
                    System.out.println(rewards / WriteInTarget);
                    rewards = 0.0;
                } else if (agent.view == 2) {
                    //KD
                    System.out.println("KD");
                    if (bots.die != 0)
                        System.out.println((double) ((double) bots.kill / (double) bots.die));
                    else
                        System.out.println((double) bots.kill);
                } else if (agent.view == 3) {
                    System.out.println("numCode");
                    System.out.println(agent.numCode);
                }
            }
        }

    }

    private void FALCON_buffer(Bots bots) {
        bots.buff.add(new Buffer(bots.numState, bots.numAction));
        rewards += bots.r;
        bots.buff.get(bots.buff.size()).Replay_Buffer(bots.CurrentStat, bots.action, bots.r, bots.NextStat, bots.end);

    }


    private void FALCON_perf(FALCON agent, Bots bots) {
        FALCON_observe(bots);
        for (int i = 0; i < bots.numState; i++) {
            bots.NextStat[i] = bots.stat[i];
        }

        FALCON_reward_function(bots);
        FALCON_buffer(bots);
        FALCON_observe(bots);
        for (int i = 0; i < bots.numState; i++) {
            bots.CurrentStat[i] = bots.stat[i];
        }

        FALCON_SelectVAct(bots);
        bots.action = agent.Policy(bots.CurrentStat, bots.vact); //代理选择Q值
        bots.r = 0;
        bots.end = false;
        FALCON_DoAct(bots, bots.action);
        FALCON_LEARNING(agent, bots);
        FALCON_EVAL(agent, bots);

    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    public void Shooting_reward_function(Bots bots) {
        //double y=(double)info.getHealth()/100.0-bots.lastheal;
        if (!bots.end) {

            if (bots.hitdamage > 0) {
                bots.r += (double) bots.hitdamage / 100.0;
            }
            bots.hitdamage = 0;

            if (bots.r > 1) bots.r = 1;
        }
    }

    static int Shooting_numState = (2 + 3 + 7) * 2;

    //状态采样
    public void Shooting_observe(Bots bots) {

        int i = 0;
        bots.observe();

        //血量
        bots.stat[2 * i] = (double) info.getHealth() / 100.0;
        if (bots.stat[2 * i] > 1) bots.stat[2 * i] = 1.0;
        bots.stat[2 * i + 1] = 1 - bots.stat[2 * i];
        i += 1;


        Player enemy = players.getNearestVisiblePlayer(players.getVisibleEnemies().values());
        if (enemy != null) {
            bots.stat[2 * i] = (double) (info.getLocation().getDistance(enemy.getLocation()) / 1000.0);
            if (bots.stat[2 * i] > 1) bots.stat[2 * i] = 1.0;
            bots.stat[2 * i + 1] = 1 - bots.stat[2 * i];
        }

        i += 1;


        //有敌人
        if (enemy != null) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;


        //射击
        if (bots.shooting) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否被攻击
        if (senses.isBeingDamaged()) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有激光
        if (weaponry.hasWeapon(UT2004ItemType.LIGHTNING_GUN)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有minigun
        if (weaponry.hasWeapon(UT2004ItemType.MINIGUN)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有闪光炮
        if (weaponry.hasWeapon(UT2004ItemType.FLAK_CANNON)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有火箭筒
        if (weaponry.hasWeapon(UT2004ItemType.ROCKET_LAUNCHER)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有连接枪
        if (weaponry.hasWeapon(UT2004ItemType.LINK_GUN)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有突击步枪
        if (weaponry.hasWeapon(UT2004ItemType.ASSAULT_RIFLE)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有生物枪
        if (weaponry.hasWeapon(UT2004ItemType.BIO_RIFLE)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;


    }

    static int Shooting_numAction = 9;

    public void Shooting_SelectVAct(Bots bots) {
        int i = 0;
        bots.vact[i] = true;
        if (!weaponry.hasWeapon(UT2004ItemType.LIGHTNING_GUN)) {
            bots.vact[i] = false;
        }
        i += 1;

        bots.vact[i] = true;
        if (!weaponry.hasWeapon(UT2004ItemType.SHOCK_RIFLE)) {
            bots.vact[i] = false;
        }
        i += 1;

        bots.vact[i] = true;
        if (!weaponry.hasWeapon(UT2004ItemType.MINIGUN)) {
            bots.vact[i] = false;
        }
        i += 1;

        bots.vact[i] = true;
        if (!weaponry.hasWeapon(UT2004ItemType.FLAK_CANNON)) {
            bots.vact[i] = false;
        }
        i += 1;

        bots.vact[i] = true;
        if (!weaponry.hasWeapon(UT2004ItemType.ROCKET_LAUNCHER)) {
            bots.vact[i] = false;
        }
        i += 1;

        bots.vact[i] = true;
        if (!weaponry.hasWeapon(UT2004ItemType.LINK_GUN)) {
            bots.vact[i] = false;
        }
        i += 1;

        bots.vact[i] = true;
        if (!weaponry.hasWeapon(UT2004ItemType.ASSAULT_RIFLE)) {
            bots.vact[i] = false;
        }
        i += 1;

        bots.vact[i] = true;
        if (!weaponry.hasWeapon(UT2004ItemType.BIO_RIFLE)) {
            bots.vact[i] = false;
        }
        i += 1;

        bots.vact[i] = true;
        Player enemy = players.getNearestVisiblePlayer(players.getVisibleEnemies().values());
        if (enemy == null) {
            bots.vact[i] = false;
        }
        i += 1;


    }

    public void Shooting_ChangeWeapon(Bots bots, UT2004ItemType weap) {
        weaponry.changeWeapon(weaponry.getWeapon(weap));
    }


    public void Shooting_shoot(Bots bots) {
        bots.enemy = players.getNearestVisiblePlayer(players.getVisibleEnemies().values());
        if (bots.enemy != null) {
            shoot.shoot(shoot.getActualWeaponPref(), bots.enemy);
        }
        //bot.getBotName().setInfo("shooting");
    }

    //选择动作
    public void Shooting_DoAct(Bots bots, int action) {
        int i = 0;
        if (action == i) {
            Shooting_ChangeWeapon(bots, UT2004ItemType.LIGHTNING_GUN);
            return;
        }
        i += 1;
        if (action == i) {
            Shooting_ChangeWeapon(bots, UT2004ItemType.SHOCK_RIFLE);
            return;
        }
        i += 1;
        if (action == i) {
            Shooting_ChangeWeapon(bots, UT2004ItemType.MINIGUN);
            return;
        }
        i += 1;
        if (action == i) {
            Shooting_ChangeWeapon(bots, UT2004ItemType.FLAK_CANNON);
            return;
        }
        i += 1;
        if (action == i) {
            Shooting_ChangeWeapon(bots, UT2004ItemType.ROCKET_LAUNCHER);
            return;
        }
        i += 1;
        if (action == i) {
            Shooting_ChangeWeapon(bots, UT2004ItemType.LINK_GUN);
            return;
        }
        i += 1;
        if (action == i) {
            Shooting_ChangeWeapon(bots, UT2004ItemType.ASSAULT_RIFLE);
            return;
        }
        i += 1;
        if (action == i) {
            Shooting_ChangeWeapon(bots, UT2004ItemType.BIO_RIFLE);
            return;
        }
        i += 1;
        if (action == i) {
            Shooting_shoot(bots);
            return;
        }
        i += 1;

    }


    private void Shooting_perf(FALCON agent, Bots bots) {
        Shooting_observe(bots);                    //////////////////////
        for (int i = 0; i < bots.numState; i++) {
            bots.NextStat[i] = bots.stat[i];
        }

        Shooting_reward_function(bots);            ///////////////////////
        FALCON_buffer(bots);

        Shooting_observe(bots);                    ///////////////////////////
        for (int i = 0; i < bots.numState; i++) {
            bots.CurrentStat[i] = bots.stat[i];
        }

        Shooting_SelectVAct(bots);                    //////////////////
        bots.action = agent.Policy(bots.CurrentStat, bots.vact); //代理选择Q值
        bots.r = 0;
        bots.end = false;
        Shooting_DoAct(bots, bots.action);            ///////////////////////
        stopshooting();

        FALCON_LEARNING(agent, bots);
        FALCON_EVAL(agent, bots);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    public void Focus_reward_function(Bots bots) {
        double y = (double) info.getHealth() / 100.0 - bots.lastheal;

        if (!bots.end) {
            bots.r += y;
            bots.lastheal = (double) info.getHealth() / 100.0;

            if (bots.hitdamage > 0) {
                bots.r += (double) (bots.hitdamage) / 100.0;
            }
            bots.hitdamage = 0;

            if (bots.r > 1) bots.r = 1;
        }
    }


    static int Focus_numState = (2 + 3 + 7) * 2;

    //状态采样
    public void Focus_observe(Bots bots) {

        int i = 0;
        bots.observe();

        //血量
        bots.stat[2 * i] = (double) info.getHealth() / 100.0;
        if (bots.stat[2 * i] > 1) bots.stat[2 * i] = 1.0;
        bots.stat[2 * i + 1] = 1 - bots.stat[2 * i];
        i += 1;


        Player enemy = players.getNearestVisiblePlayer(players.getVisibleEnemies().values());
        if (enemy != null) {
            bots.stat[2 * i] = (double) (info.getLocation().getDistance(enemy.getLocation()) / 1000.0);
            if (bots.stat[2 * i] > 1) bots.stat[2 * i] = 1.0;
            bots.stat[2 * i + 1] = 1 - bots.stat[2 * i];
        }

        i += 1;


        //有敌人
        if (enemy != null) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;


        //射击
        if (bots.shooting) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否被攻击
        if (senses.isBeingDamaged()) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有激光
        if (weaponry.hasWeapon(UT2004ItemType.LIGHTNING_GUN)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有minigun
        if (weaponry.hasWeapon(UT2004ItemType.MINIGUN)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有闪光炮
        if (weaponry.hasWeapon(UT2004ItemType.FLAK_CANNON)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有火箭筒
        if (weaponry.hasWeapon(UT2004ItemType.ROCKET_LAUNCHER)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有连接枪
        if (weaponry.hasWeapon(UT2004ItemType.LINK_GUN)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有突击步枪
        if (weaponry.hasWeapon(UT2004ItemType.ASSAULT_RIFLE)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有生物枪
        if (weaponry.hasWeapon(UT2004ItemType.BIO_RIFLE)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;


    }

    static int Focus_numAction = 11;

    public void Focus_SelectVAct(Bots bots) {
        int i = 0;
        bots.vact[i] = true;
        if (bots.item != null)
            if (navigation.isNavigatingToItem() && bots.item.getType() != UT2004ItemType.LIGHTNING_GUN) {
                bots.vact[i] = false;
            }
        i += 1;

        bots.vact[i] = true;
        if (bots.item != null)
            if (navigation.isNavigatingToItem() && bots.item.getType() != UT2004ItemType.SHOCK_RIFLE) {
                bots.vact[i] = false;
            }
        i += 1;

        bots.vact[i] = true;

        if (bots.item != null)
            if (navigation.isNavigatingToItem() && bots.item.getType() != UT2004ItemType.MINIGUN) {
                bots.vact[i] = false;
            }
        i += 1;

        bots.vact[i] = true;
        if (bots.item != null)
            if (navigation.isNavigatingToItem() && bots.item.getType() != UT2004ItemType.FLAK_CANNON) {
                bots.vact[i] = false;
            }
        i += 1;

        bots.vact[i] = true;
        if (bots.item != null)
            if (navigation.isNavigatingToItem() && bots.item.getType() != UT2004ItemType.ROCKET_LAUNCHER) {
                bots.vact[i] = false;
            }
        i += 1;

        bots.vact[i] = true;
        if (bots.item != null)
            if (navigation.isNavigatingToItem() && bots.item.getType() != UT2004ItemType.LINK_GUN) {
                bots.vact[i] = false;
            }
        i += 1;

        bots.vact[i] = true;
        if (bots.item != null)
            if (navigation.isNavigatingToItem() && bots.item.getType() != UT2004ItemType.ASSAULT_RIFLE) {
                bots.vact[i] = false;
            }
        i += 1;

        bots.vact[i] = true;
        if (bots.item != null)
            if (navigation.isNavigatingToItem() && bots.item.getType() != UT2004ItemType.BIO_RIFLE) {
                bots.vact[i] = false;
            }
        i += 1;


        bots.vact[i] = true;
        Item item = items.getPathNearestSpawnedItem(ItemType.Category.HEALTH);
        if (item == null) {
            bots.vact[i] = false;
        }
        i += 1;


        /////

        bots.vact[i] = true;

        if (bots.enemy == null) {
            bots.vact[i] = false;
        }


        i += 1;

        ////////


        bots.vact[i] = true;

        i += 1;


    }

    public void Focus_naviWeapon(Bots bots, UT2004ItemType weap) {
        if (navigation.isNavigatingToItem())
            return;

        bots.interesting = new ArrayList<Item>();
        bots.interesting.addAll(items.getSpawnedItems(weap).values());
        bots.item = MyCollections.getRandom(tabooItems.filter(bots.interesting));
        if (bots.item != null) {
            navigation.navigate(bots.item);
            bot.getBotName().setInfo(weap.getName());
        }


    }

    public void Focus_MedKit(Bots bots) {
        bots.item = items.getPathNearestSpawnedItem(ItemType.Category.HEALTH);
        if (bots.item != null) {
            navigation.navigate(bots.item);
            bot.getBotName().setInfo("Medic");
        }
    }

    public void Focus_naviEnemy(Bots bots) {
        bots.item = null;

        if (navigation.isNavigatingToPlayer()) {
            return;
        }
        if (bots.enemy != null) {
            navigation.navigate(bots.enemy);
            bot.getBotName().setInfo("navienemy");
        }
    }


    //选择动作
    public void Focus_DoAct(Bots bots, int action) {
        int i = 0;
        if (action == i) {
            Focus_naviWeapon(bots, UT2004ItemType.LIGHTNING_GUN);
            return;
        }
        i += 1;
        if (action == i) {
            Focus_naviWeapon(bots, UT2004ItemType.SHOCK_RIFLE);
            return;
        }
        i += 1;
        if (action == i) {
            Focus_naviWeapon(bots, UT2004ItemType.MINIGUN);
            return;
        }
        i += 1;
        if (action == i) {
            Focus_naviWeapon(bots, UT2004ItemType.FLAK_CANNON);
            return;
        }
        i += 1;
        if (action == i) {
            Focus_naviWeapon(bots, UT2004ItemType.ROCKET_LAUNCHER);
            return;
        }
        i += 1;
        if (action == i) {
            Focus_naviWeapon(bots, UT2004ItemType.LINK_GUN);
            return;
        }
        i += 1;
        if (action == i) {
            Focus_naviWeapon(bots, UT2004ItemType.ASSAULT_RIFLE);
            return;
        }
        i += 1;
        if (action == i) {
            Focus_naviWeapon(bots, UT2004ItemType.BIO_RIFLE);
            return;
        }
        i += 1;
        if (action == i) {
            Focus_MedKit(bots);
            return;
        }
        i += 1;
        if (action == i) {
            Focus_naviEnemy(bots);
            return;
        }
        i += 1;
        if (action == i) {
            bots.item = null;
            navigation.stopNavigation();
            bot.getBotName().setInfo("stop");
            return;
        }
        i += 1;

    }


    private void Focus_perf(FALCON agent, Bots bots) {
        Focus_observe(bots);                    //////////////////////
        for (int i = 0; i < bots.numState; i++) {
            bots.NextStat[i] = bots.stat[i];
        }

        Focus_reward_function(bots);            ///////////////////////
        FALCON_buffer(bots);

        Focus_observe(bots);                    ///////////////////////////
        for (int i = 0; i < bots.numState; i++) {
            bots.CurrentStat[i] = bots.stat[i];
        }

        Focus_SelectVAct(bots);                    //////////////////
        bots.action = agent.Policy(bots.CurrentStat, bots.vact); //代理选择Q值
        bots.r = 0;
        bots.end = false;
        Focus_DoAct(bots, bots.action);            ///////////////////////
        FALCON_LEARNING(agent, bots);
        FALCON_EVAL(agent, bots);
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    public void Move_reward_function(Bots bots) {
        double y = (double) info.getHealth() / 100.0 - bots.lastheal;

        if (!bots.end) {
            if (y > 0) {
                bots.r += 0.25;
            } else if (y < 0) {
                bots.r -= 0.25;
            }
            bots.lastheal = (double) info.getHealth() / 100.0;

            if (bots.hitdamage > 0) {
                bots.r += 0.75;
            }
            bots.hitdamage = 0;

            if (bots.r > 1) bots.r = 1;
        }
    }


    static int Move_numState = (2 + 3 + 7 + 5) * 2;

    //状态采样
    public void Move_observe(Bots bots) {

        int i = 0;
        bots.observe();

        //血量
        bots.stat[2 * i] = (double) info.getHealth() / 100.0;
        if (bots.stat[2 * i] > 1) bots.stat[2 * i] = 1.0;
        bots.stat[2 * i + 1] = 1 - bots.stat[2 * i];
        i += 1;


        Player enemy = players.getNearestVisiblePlayer(players.getVisibleEnemies().values());
        if (enemy != null) {
            bots.stat[2 * i] = (double) (info.getLocation().getDistance(enemy.getLocation()) / 1000.0);
            if (bots.stat[2 * i] > 1) bots.stat[2 * i] = 1.0;
            bots.stat[2 * i + 1] = 1 - bots.stat[2 * i];
        }

        i += 1;


        //有敌人
        if (enemy != null) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;


        //射击
        if (bots.shooting) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否被攻击
        if (senses.isBeingDamaged()) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有激光
        if (weaponry.hasWeapon(UT2004ItemType.LIGHTNING_GUN)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有minigun
        if (weaponry.hasWeapon(UT2004ItemType.MINIGUN)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有闪光炮
        if (weaponry.hasWeapon(UT2004ItemType.FLAK_CANNON)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有火箭筒
        if (weaponry.hasWeapon(UT2004ItemType.ROCKET_LAUNCHER)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有连接枪
        if (weaponry.hasWeapon(UT2004ItemType.LINK_GUN)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有突击步枪
        if (weaponry.hasWeapon(UT2004ItemType.ASSAULT_RIFLE)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        //是否有生物枪
        if (weaponry.hasWeapon(UT2004ItemType.BIO_RIFLE)) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        if (!raycasting.getAllRaysInitialized().getFlag()) {
            return;
        }

        bots.sensorFront = bots.front.isResult();
        if (bots.sensorFront) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        bots.sensorLeft90 = bots.left90.isResult();
        if (bots.sensorLeft90) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        bots.sensorRight90 = bots.right90.isResult();
        if (bots.sensorRight90) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        bots.sensorLeft45 = bots.left45.isResult();
        if (bots.sensorLeft45) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;

        bots.sensorRight45 = bots.right45.isResult();
        if (bots.sensorRight45) {
            bots.stat[2 * i] = 0;
            bots.stat[2 * i + 1] = 1;
        }

        i += 1;


    }

    static int Move_numAction = 2 + 3 + 2;

    public void Move_SelectVAct(Bots bots) {
        int i = 0;
        bots.vact[i] = true;

        if (bots.sensorRight45) {
            bots.vact[i] = false;
        }

        i += 1;

        bots.vact[i] = true;
        if (bots.sensorLeft45) {
            bots.vact[i] = false;
        }

        i += 1;

        ////
        bots.vact[i] = true;
        if (bots.sensorRight90) {
            bots.vact[i] = false;
        }
        i += 1;

        bots.vact[i] = true;
        if (bots.sensorLeft90) {
            bots.vact[i] = false;
        }
        i += 1;

        bots.vact[i] = true;

        i += 1;

        ////
        bots.vact[i] = true;

        i += 1;

        bots.vact[i] = true;

        i += 1;

    }

    private static final double FOCUS_DISTANCE = 3000;

    public void strafeForward(double distance) {
        Location startLoc = info.getLocation();
        Location directionVector = info.getRotation().toLocation();
        Location targetVec = directionVector.cross(new Location(0, 0, 0)).getNormalized().scale(-distance);

        getAct().act(
                new Move()
                        .setFirstLocation(startLoc.add(targetVec))
                        .setFocusLocation(startLoc.add(directionVector.getNormalized()
                                .scale(FOCUS_DISTANCE))));
    }

    public void strafeBack(double distance) {
        Location startLoc = info.getLocation();
        Location directionVector = info.getRotation().toLocation();
        Location targetVec = directionVector.cross(new Location(0, 0, 0)).getNormalized().scale(-distance);

        getAct().act(
                new Move()
                        .setFirstLocation(startLoc.add(targetVec))
                        .setFocusLocation(startLoc.add(directionVector.getNormalized()
                        )));
    }

    //选择动作
    public int turnSleep = 250;
    public float moveSpeed = 0.6f;
    public int smallTurn = 30;
    public int bigTurn = 90;

    public void Move_DoAct(Bots bots, int action) {
        int i = 0;
        if (action == i) {
            move.turnHorizontal(smallTurn);
            return;
        }
        i += 1;
        if (action == i) {
            move.turnHorizontal(-smallTurn);
            return;
        }
        i += 1;

        if (action == i) {
            move.strafeRight(50);
            ;
            return;
        }
        i += 1;
        if (action == i) {
            move.strafeLeft(50);
            return;
        }
        i += 1;
        if (action == i) {
            strafeBack(50);
            return;
        }
        i += 1;

        if (action == i) {
            move.jump();
            return;
        }
        i += 1;
        if (action == i) {
            ;
            return;
        }
        i += 1;


    }


    private void Move_perf(FALCON agent, Bots bots) {
        Move_observe(bots);                    //////////////////////
        for (int i = 0; i < bots.numState; i++) {
            bots.NextStat[i] = bots.stat[i];
        }
        Move_reward_function(bots);            ///////////////////////
        FALCON_buffer(bots);
        Move_observe(bots);                    ///////////////////////////
        for (int i = 0; i < bots.numState; i++) {
            bots.CurrentStat[i] = bots.stat[i];
        }
        Move_SelectVAct(bots);                    //////////////////
        bots.action = agent.Policy(bots.CurrentStat, bots.vact); //代理选择Q值
        bots.r = 0;
        bots.end = false;
        Move_DoAct(bots, bots.action);            ///////////////////////
        FALCON_LEARNING(agent, bots);
        FALCON_EVAL(agent, bots);
    }
 /*   
	agent.QEpsilon
	agent.QEpsilonDecay
	agent.beta
	agent.QGamma
	agent.QAlpha
	agent.epilson
	agent.gamma[]
	agent.alpha[]
	agent.rho[]
	*/
}